#include "TcpServer.hpp"
#include "Log.hpp"
#define FD_NONE -1
const int PORT = 8081;
const int NUM = 100;
class SelectType
{
public:
    SelectType(int port = PORT, int num = NUM)
        : _port(port), _num(num)
    {
        fd_arr.resize(num, FD_NONE);
        tcpserver = new TcpServer(port);
        _listensock = tcpserver->Sock;
        fd_arr[0] = _listensock;
    }
    ~SelectType()
    {
        if (_listensock >= 0)
            close(_listensock);
    }
    void Handler(fd_set *rdf)
    {
        for (int i = 0; i < _num; i++)
        {
            if (FD_ISSET(fd_arr[i], rdf))
            {
                if (fd_arr[i] == _listensock)
                {
                    Accepter();
                }
                else
                {
                    Recver();
                }
            }
        }
    }
    void Accepter()
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof peer;
        int sock = accept(_listensock, (struct sockaddr *)&peer, &len);
        int i = 1;
        for (; i < _num; i++)
        {
            if (fd_arr[i] == FD_NONE)
                break;
        }
        if (i == _num)
            LOG(WARNING, "select链接的文件描述符已满,此次链接失败");
        else
            fd_arr[i] = sock;
    }
    void Recver(int sock)
    {
        char buffer[1024] = {0};
        int n = recv(sock, buffer, sizeof buffer, 0);
        if (n > 0)
        {
            cout << sock << ": " << buffer << endl;
        }
        else if (n == 0)
        {
            string message;
            message += to_string(sock);
            message += "号文件描述符已关闭";
            LOG(WARNING, message);
            fd_arr[sock] = FD_NONE;
        }
        else
        {
            LOG(ERROR, "读取错误");
            fd_arr[sock] = FD_NONE;
        }
    }
    void Loop()
    {
        while (1)
        {
            fd_set rfd;
            FD_ZERO(&rfd);
            int maxfd = 0;
            for (int i = 0; i < _num; i++)
            {
                if (fd_arr[i] == FD_NONE)
                    continue;
                FD_SET(fd_arr[i], &rfd);
                if (maxfd < fd_arr[i])
                    maxfd = fd_arr[i];
            }
            int n = select(maxfd + 1, &rfd, nullptr, nullptr, nullptr);
            switch (n)
            {
            case 0:
                break;
            case -1:
            {
                LOG(WARNING, "select Error");
                break;
            }
            default:
            {
                Handler();
                break;
            }
            }
        }
    }

private:
    int _port;
    int _num;
    int _listensock;
    vector<int> fd_arr;
    TcpServer *tcpserver;
}